package edu.client;


import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TabPanel;

import edu.client.IngenieriaService.IngenieriaService;
import edu.client.IngenieriaService.IngenieriaServiceAsync;
import edu.shared.DTO.ClaseProductoDTO;
import edu.shared.DTO.ElementoProductoDTO;
import edu.shared.DTO.MaterialProductoDTO;
import edu.shared.DTO.ProductoDTO;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ChangeEvent;
	

public class P_EliminarProducto extends Composite	 {
	
	//columnas para la tabla productos
	private static final int COL_CHECK = 0;
	private static final int COL_CODIGO = 1;
	private static final int COL_CLASE = 2;
	private static final int COL_ELEMENTO = 3;
	private static final int COL_MATERIAL = 4;
	private static final int COL_MEDIDA_FIJA = 5;
	private static final int COL_MAS_INFO = 6;
	
	private ListBox cbClase;
	private ListBox cbElemento;
	private ListBox cbMaterial;
	
	private FlexTable ftProductos;
	
	private TabPanel tbPadre;
	private IngenieriaServiceAsync ingenieriaService;
	private List<ClaseProductoDTO> clases;
	private List<ElementoProductoDTO> elementos;
	private List<MaterialProductoDTO> materiales;
	private List<ProductoDTO> productos;
	
	private Button btnEliminarProducto;
	
	public P_EliminarProducto(TabPanel padre)
	{
		this.tbPadre = padre;		
		ingenieriaService = GWT.create(IngenieriaService.class);
		
		LayoutPanel layoutPanel = new LayoutPanel();
		initWidget(layoutPanel);
		layoutPanel.setSize((Window.getClientWidth() - 55) + "px", "668px");
		
		Label lblFiltrarPor = new Label("FILTROS");
		lblFiltrarPor.setStyleName("labelTitulo");
		layoutPanel.add(lblFiltrarPor);
		layoutPanel.setWidgetLeftWidth(lblFiltrarPor, 2.5, Unit.PCT, 95.0, Unit.PCT);
		layoutPanel.setWidgetTopHeight(lblFiltrarPor, 15.0, Unit.PX, 50.0, Unit.PX);
		
		Label lblClase = new Label("CLASE:");
		lblClase.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
		layoutPanel.add(lblClase);
		layoutPanel.setWidgetLeftWidth(lblClase, 0.0, Unit.PCT, 17.3, Unit.PCT);
		layoutPanel.setWidgetTopHeight(lblClase, 80.0, Unit.PX, 19.0, Unit.PX);
		
		cbClase = new ListBox();
		
		//cuando el combobox de clases cambia de item seleccionado
		cbClase.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				cargarComboElemento();
			}
		});
		
		layoutPanel.add(cbClase);
		layoutPanel.setWidgetLeftWidth(cbClase, 17.5, Unit.PCT, 25.0, Unit.PCT);
		layoutPanel.setWidgetTopHeight(cbClase, 75.0, Unit.PX, 32.0, Unit.PX);
		
		Label lblElemento = new Label("ELEMENTO:");
		lblElemento.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
		layoutPanel.add(lblElemento);
		layoutPanel.setWidgetLeftWidth(lblElemento, 50.0, Unit.PCT, 19.8, Unit.PCT);
		layoutPanel.setWidgetTopHeight(lblElemento, 80.0, Unit.PX, 19.0, Unit.PX);
		
		cbElemento = new ListBox();
		layoutPanel.add(cbElemento);
		layoutPanel.setWidgetLeftWidth(cbElemento, 70.0, Unit.PCT, 25.0, Unit.PCT);
		layoutPanel.setWidgetTopHeight(cbElemento, 75.0, Unit.PX, 32.0, Unit.PX);
		
		Label lblMaterial = new Label("MATERIAL:");
		lblMaterial.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
		layoutPanel.add(lblMaterial);
		layoutPanel.setWidgetLeftWidth(lblMaterial, 0.0, Unit.PCT, 17.3, Unit.PCT);
		layoutPanel.setWidgetTopHeight(lblMaterial, 115.0, Unit.PX, 19.0, Unit.PX);
		
		cbMaterial = new ListBox();
		layoutPanel.add(cbMaterial);
		layoutPanel.setWidgetLeftWidth(cbMaterial, 17.5, Unit.PCT, 25.0, Unit.PCT);
		layoutPanel.setWidgetTopHeight(cbMaterial, 110.0, Unit.PX, 32.0, Unit.PX);
		
		Button btnFiltrar = new Button();
		
		//cuando se presiona el botón filtrar
		btnFiltrar.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				filtrarProductos();
			}
		});
		
		btnFiltrar.setText("BUSCAR");
		layoutPanel.add(btnFiltrar);
		layoutPanel.setWidgetLeftWidth(btnFiltrar, 45.0, Unit.PCT, 10.0, Unit.PCT);
		layoutPanel.setWidgetTopHeight(btnFiltrar, 150.0, Unit.PX, 28.0, Unit.PX);
		
		Label lblProductos = new Label("PRODUCTOS");
		lblProductos.setStyleName("labelTitulo");
		layoutPanel.add(lblProductos);
		layoutPanel.setWidgetLeftWidth(lblProductos, 2.5, Unit.PCT, 95.0, Unit.PCT);
		layoutPanel.setWidgetTopHeight(lblProductos, 180.0, Unit.PX, 50.0, Unit.PX);
		
		ScrollPanel spProductos = new ScrollPanel();
		spProductos.setStyleName("tabla");
		layoutPanel.add(spProductos);
		layoutPanel.setWidgetLeftWidth(spProductos, 5.0, Unit.PCT, 90.0, Unit.PCT);
		layoutPanel.setWidgetTopHeight(spProductos, 245.0, Unit.PX, 250.0, Unit.PX);
		
		ftProductos = new FlexTable();
		spProductos.setWidget(ftProductos);
		ftProductos.setSize("100%", "100%");
		
		//cargamos el encabezado de la tabla
		// columna chekeo
		ftProductos.setText(0, COL_CHECK, "");
		ftProductos.getCellFormatter().setWidth(0, COL_CHECK, "5%");
		
		// columna codigo
		ftProductos.setText(0, COL_CODIGO, "CÓDIGO");
		ftProductos.getCellFormatter().setWidth(0, COL_CODIGO, "10%");
		
		// columna clase
		ftProductos.setText(0, COL_CLASE, "CLASE");
		ftProductos.getCellFormatter().setWidth(0, COL_CLASE, "21.5%");
				
		// columna elemento
		ftProductos.setText(0, COL_ELEMENTO, "ELEMENTO");
		ftProductos.getCellFormatter().setWidth(0, COL_ELEMENTO, "25%");
				
		// columna material
		ftProductos.setText(0, COL_MATERIAL, "MATERIAL");
		ftProductos.getCellFormatter().setWidth(0, COL_MATERIAL, "21.5%");
		
		// columna medida fija
		ftProductos.setText(0, COL_MEDIDA_FIJA, "MEDIDA FIJA");
		ftProductos.getCellFormatter().setWidth(0, COL_MEDIDA_FIJA, "10%");
		
		// columna más información
		ftProductos.setText(0, COL_MAS_INFO, "+ INFO");
		ftProductos.getCellFormatter().setWidth(0, COL_MAS_INFO, "7%");
		
		// seteamos el estilo a los encabezados
		ftProductos.getRowFormatter().addStyleName(0, "tablaEncabezado");
		
		Label lblPie = new Label("");
		lblPie.setStyleName("labelTitulo");
		layoutPanel.add(lblPie);
		layoutPanel.setWidgetLeftWidth(lblPie, 2.5, Unit.PCT, 95.0, Unit.PCT);
		layoutPanel.setWidgetTopHeight(lblPie, 525.0, Unit.PX, 50.0, Unit.PX);
		
		Button btnSalir = new Button("");
		
		//cuando se presiona el botón salir
		btnSalir.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				//cerramos la pantalla
				tbPadre.remove(Validaciones.numeroElemento(tbPadre, "ELIMINAR PRODUCTO"));
			}
		});
		
		btnSalir.setText("SALIR");
		layoutPanel.add(btnSalir);
		layoutPanel.setWidgetRightWidth(btnSalir, 5.0, Unit.PCT, 10.0, Unit.PCT);
		layoutPanel.setWidgetBottomHeight(btnSalir, 15.0, Unit.PX, 28.0, Unit.PX);
		
		btnEliminarProducto = new Button("");
		
		btnEliminarProducto.setText("ELIMINAR");
		layoutPanel.add(btnEliminarProducto);
		layoutPanel.setWidgetRightWidth(btnEliminarProducto, 17.5, Unit.PCT, 10.0, Unit.PCT);
		layoutPanel.setWidgetBottomHeight(btnEliminarProducto, 15.0, Unit.PX, 28.0, Unit.PX);
		
		//cuando se presiona el botón eliminar producto
		btnEliminarProducto.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				
				btnEliminarProducto.setEnabled(false);
				
				eliminarProducto();
			}
		});
		
		cargarComboClase();
		cargarComboMaterial();
		cargarProductos();
	}
	
	/**
	 * Método que carga el combobox de clases con las clases cargadas en la base de datos
	 */
	private void cargarComboClase()
	{
		ingenieriaService.buscarClasesProducto(new AsyncCallback<List<ClaseProductoDTO>>()
		{
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("ERROR EN EL SERVICIO" + '\n' + '\n' + caught.getMessage());
			}
	
			@Override
			public void onSuccess(List<ClaseProductoDTO> result) {
				clases = result;
				
				try{
					//si la lista de clases es vacía entonces no existen productos cargados
					if(clases.size() == 0)
						throw new Exception("No existen productos cargados en la base de datos.");
					
					else
					{
						cbClase.addItem("TODAS LAS CLASES");
						
						//si hay clases en la base de datos, las cargamos en el combo de clases
						for(ClaseProductoDTO clase : clases)
							cbClase.addItem(clase.getCodigo() + " - " + clase.getNombre());
						
						cargarComboElemento();
					}
				}
				
				catch(Exception e)
				{
					Window.alert(e.getMessage());
				}
			}
		});
	}
	
	/**
	 * Método que carga el combobox de elementos con los elementos cargados en la base de datos
	 */
	private void cargarComboElemento()
	{
		cbElemento.clear();
		cbElemento.addItem("TODOS LOS ELEMENTOS");
		
		//obtenemos el código de clase seleccionada
		int claseSeleccionada = cbClase.getSelectedIndex();
		
		//si clase seleccionada es igual a 0 significa que se ha seleccionado "TODAS LAS CLASES" en el combobox de clases.
		//Caso contrario buscamos todas las subclases
		if(claseSeleccionada != 0)
		{
			int codigoClase = clases.get(claseSeleccionada-1).getCodigo();
			
			ingenieriaService.buscarElementosProducto(codigoClase, new AsyncCallback<List<ElementoProductoDTO>>()
			{
	
				@Override
				public void onFailure(Throwable caught) {
					Window.alert("ERROR EN EL SERVICIO" + '\n' + '\n' + caught.getMessage());			
				}
	
				@Override
				public void onSuccess(List<ElementoProductoDTO> result) {
					elementos = result;
					
					//cargamos el combo de elementos
					for(ElementoProductoDTO elemento : elementos)
						cbElemento.addItem(elemento.getCodigo() + " - " + elemento.getNombre());
				}
			});
		}
	}
		
	/**
	 * Método que carga el combobox de materiales con los materiales cargados en la base de datos
	 */
	private void cargarComboMaterial()
	{
		ingenieriaService.buscarMaterialesProducto(new AsyncCallback<List<MaterialProductoDTO>>()
		{
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("ERROR EN EL SERVICIO" + '\n' + '\n' + caught.getMessage());	
			}

			@Override
			public void onSuccess(List<MaterialProductoDTO> result) {
				materiales = result;
				
				cbMaterial.addItem("TODOS LOS MATERIALES");
				
				//cargamos el combobox de materiales
				for(MaterialProductoDTO material : materiales)
					cbMaterial.addItem(material.getCodigo() + " - " + material.getNombre());
			}
		});
	}
	
	/**
	 * Método que carga en la base de datos todos los productos cargados en la base de datos
	 */
	private void cargarProductos()
	{
		//llamamos a buscar productos con todos cero como id de clase, material y medida fija para que traiga todos los productos
		ingenieriaService.buscarProductos(0, 0, 0, new AsyncCallback<List<ProductoDTO>>()
		{
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("ERROR EN EL SERVICIO" + '\n' + '\n' + caught.getMessage());		
			}
	
			@Override
			public void onSuccess(List<ProductoDTO> result) {
				productos = result;
				cargarTablaProductos();
			}
		});
	}
	
	
	/**
	 * Método que filtra los productos dependiendo de la clase, elemento y material seleccionado.
	 */
	private void filtrarProductos()
	{
		//recuperamos el código de clase
		int claseSeleccionada = cbClase.getSelectedIndex();
		int codigoClase = 0;
		
		if(claseSeleccionada != 0)
			codigoClase = clases.get(claseSeleccionada-1).getCodigo();
		
		//recuperamos el código de elemento seleccionado
		int elementoSeleccionado = cbElemento.getSelectedIndex();
		int codigoElemento = 0;
		
		if(elementoSeleccionado != 0)
			codigoElemento = elementos.get(elementoSeleccionado-1).getCodigo();
		
		//recuperamos el código de material seleccionado
		int materialSeleccionado = cbMaterial.getSelectedIndex();
		int codigoMaterial = 0;
		
		if(materialSeleccionado != 0)
			codigoMaterial = materiales.get(materialSeleccionado-1).getCodigo();
		
		
		ingenieriaService.buscarProductos(codigoClase, codigoElemento, codigoMaterial, new AsyncCallback<List<ProductoDTO>>()
		{
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("ERROR EN EL SERVICIO" + '\n' + '\n' + caught.getMessage());				
			}

			@Override
			public void onSuccess(List<ProductoDTO> result) {
				productos = result;			
				cargarTablaProductos();
				
				if(productos.size() == 0)
					Window.alert("No existen productos con las características seleccionadas.");
			}	
		});
	}
	
	
	/**
	 * Método que carga la tabla de productos
	 */
	private void cargarTablaProductos()
	{
		//borramos todas las filas de la tabla de productos
		ftProductos.clear();
		
		int numeroFila = 1;
		
		// cargamos el producto a la tabla
		for(ProductoDTO producto : productos){
	
			//generamos el código del producto
			String codigoProducto = completarCeros(producto.getElemento().getClase().getCodigo()) + "-" + 
									completarCeros(producto.getElemento().getCodigo()) + "-" + 
									completarCeros(producto.getMaterial().getCodigo()) + "-" +
									completarCeros(producto.getMedidaFija().getCodigo());
			
			
			//columna check
			ftProductos.setWidget(numeroFila, COL_CHECK, new RadioButton("producto seleccionado",""));
			ftProductos.getFlexCellFormatter().setHorizontalAlignment(numeroFila, COL_CHECK, HasHorizontalAlignment.ALIGN_CENTER);
			
			//columna código
			ftProductos.setWidget(numeroFila, COL_CODIGO, new Label(codigoProducto));
			ftProductos.getCellFormatter().setWordWrap(numeroFila, COL_CODIGO, true);
			
			// columna clase
			ftProductos.setWidget(numeroFila, COL_CLASE, new Label(producto.getElemento().getClase().getNombre()));
			ftProductos.getCellFormatter().setWordWrap(numeroFila, COL_CLASE, true);
	
			// columna elemento
			ftProductos.setWidget(numeroFila, COL_ELEMENTO, new Label(producto.getElemento().getNombre()));
			ftProductos.getCellFormatter().setWordWrap(numeroFila, COL_ELEMENTO, true);
	
			// columna material
			ftProductos.setWidget(numeroFila, COL_MATERIAL, new Label(producto.getMaterial().getNombre()));
			ftProductos.getCellFormatter().setWordWrap(numeroFila, COL_MATERIAL, true);
	
			// columna medida fija
			ftProductos.setWidget(numeroFila, COL_MEDIDA_FIJA, new Label(producto.getMedidaFija().getMedida()));
			ftProductos.getCellFormatter().setWordWrap(numeroFila, COL_MEDIDA_FIJA, true);
			
			// imagen más información
			Label info = new Label("");
			info.setSize("16px", "16px");
			info.setStyleName("labelInfo");
			
			//cuando se presiona "más información"
			info.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					
					//obtenemos la celda en donde se hizo click
					Cell celda = ftProductos.getCellForEvent(event);
					
					//obtenemos el nombre del proveedor. Restamos 1 al row index porque la fila 1 es el encabezado
					ProductoDTO producto = productos.get(celda.getRowIndex() - 1);
					
					cargarMasInformacionProducto(producto);
				}
			});
			
			// columna más información
			ftProductos.setWidget(numeroFila, COL_MAS_INFO, info);
			ftProductos.getFlexCellFormatter().setHorizontalAlignment(numeroFila, COL_MAS_INFO, HasHorizontalAlignment.ALIGN_CENTER);
			
			//seteamos el estilo de renglón de tabla
			ftProductos.getRowFormatter().setStyleName(numeroFila, "tablaRenglon");
			
			numeroFila++;
		}		
	}
	
	/**
	 * Método que agrega un cero a los códigos de un dígito.
	 * @param codigo. Código original.
	 * @return String. Retorna el código rellenado con el creo, si es necesario.
	 */
	private String completarCeros(int codigo)
	{
		if(codigo < 10)
			return "0"+codigo;
		
		else
			return codigo+"";
	}
		
	
	private void cargarMasInformacionProducto(ProductoDTO producto)
	{
		
		//creamos el popup "más información" de producto
		final P_DetalleProducto popUpMasInfo = new P_DetalleProducto(producto);
		
		//seteamos sus propiedades y la mostramos en pantalla
		popUpMasInfo.setGlassEnabled(true);
		popUpMasInfo.center();
		popUpMasInfo.show();
	}
	
	/**
	 * Método que elimina de la base de datos el producto seleccionado en la
	 */
	private void eliminarProducto()
	{
		//buscamos la fila seleccionada en la tabla de productos
		int filaSeleccionada = -1;
		int i = 1;
		
		while(i < ftProductos.getRowCount() && filaSeleccionada == -1)
		{
			RadioButton radiobutton = (RadioButton) ftProductos.getWidget(i, COL_CHECK);
			
			if(radiobutton.getValue() == true)
				filaSeleccionada = i;
			
			i++;
		}
		
		//si no se seleccionó ninguna fila
		if(filaSeleccionada == -1) {
			
			Window.alert("Seleccione el producto a eliminar.");
			btnEliminarProducto.setEnabled(true);
		}
		
		//si se selección una fila, se recupera el producto que ésta representa
		else
		{
			//recuperamos el producto seleccionado. Restamos uno a la fila seleccionada porque la fila cero de la tabla es el encabezado.
			ProductoDTO producto = productos.get(filaSeleccionada-1);
			
			ingenieriaService.eliminarProducto(producto.getIdProducto(), new AsyncCallback<Boolean>()
			{
				@Override
				public void onFailure(Throwable caught) {
					Window.alert("ERROR EN EL SERVICIO." + '\n' + '\n' + caught.getMessage());
					btnEliminarProducto.setEnabled(true);					
				}

				@Override
				public void onSuccess(Boolean result) {
					Window.alert("El producto ha sido eliminado.");
					filtrarProductos();
					btnEliminarProducto.setEnabled(true);
				}		
			});
		}
	}
}